package com.rc.evcharger.action;

import com.alibaba.fastjson.JSON;
import com.rc.evcharger.biz.log.ElecPileFaultRecordLogAssemble;
import com.rc.evcharger.common.base.BaseBizAction;
import com.rc.evcharger.common.config.MqCommandConfig;
import com.rc.evcharger.common.constant.SocketConstant;
import com.rc.evcharger.common.enums.PileVersionEnum;
import com.rc.evcharger.common.mq.MqProducer;
import com.rc.evcharger.common.mq.MqProducerOld;
import com.rc.evcharger.common.terminal.*;
import com.rc.evcharger.model.elec.ElecPile;
import com.rc.evcharger.model.order.OrderInfo;
import com.rc.evcharger.service.car.TenantCarNumberService;
import com.rc.evcharger.service.elec.ElecGunService;
import com.rc.evcharger.service.elec.ElecPileService;
import com.rc.evcharger.service.elec.ElecStationService;
import com.rc.evcharger.service.member.MemberCardService;
import com.rc.evcharger.service.member.MemberInfoService;
import com.rc.evcharger.service.order.OrderInfoService;
import com.rc.evcharger.service.tenant.TenantSettingService;
import com.rc.evcharger.vo.charge.ChargeControlRet;
import com.rc.evcharger.vo.charge.ChargeReportRet;
import com.rc.evcharger.vo.charge.StopChargeReq;
import com.rc.evcharger.vo.log.ElecPileFaultRecordLog;
import com.rc.evcharger.client.ChargerClientRouter;
import com.rc.evcharger.dto.msg.TerminalMessage;
import com.rc.evcharger.dto.terminal.PowerOffResult;
import com.rc.evcharger.mq.AsyncTask;
import com.rc.evcharger.service.ChargeMessageService;
import com.rc.evcharger.service.CommandService;
import com.rc.evcharger.task.BatteryTempTask;
import com.rc.evcharger.task.ElecFullTask;
import com.rc.evcharger.task.ExOrderTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * MQ消息处理器，只是这里偏向业务逻辑
 */
@Component
public class StdBizAction implements BaseBizAction<TerminalMessage> {
    private static Logger logger = LoggerFactory.getLogger(StdBizAction.class);

    @Value("${START_TASK}")
    private Integer START_TASK;

    @Autowired
    private AsyncTask asyncTask;

    @Autowired
    private ElecPileService elecPileService;

    @Autowired
    private ExOrderTask exOrderTask;

    @Autowired
    private ChargeMessageService chargeMessageService;

    @Autowired
    private CommandService commandService;

    @Autowired
    private MemberInfoService memberService;

    @Autowired
    private MemberCardService memberCardService;

    @Autowired
    private TenantCarNumberService tenantCarNumberService;

    @Autowired
    private MqProducer mqProducer;

    @Autowired
    private MqProducerOld mqProducerOld;

    @Autowired
    private ElecGunService elecGunService;

    @Autowired
    private ElecPileFaultRecordLogAssemble elecPileFaultRecordLogAssemble;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private TenantSettingService tenantSettingService;

    @Autowired
    private MqCommandConfig mqCommandConfig;

    @Autowired
    private ElecFullTask elecFullTask;

    @Autowired
    private BatteryTempTask batteryTempTask;

    @Autowired
    private ElecStationService elecStationService;

    @Autowired
    private ChargerClientRouter chargerClientRouter;

    /**
     * 处理桩的登录指令A1
     *
     * @param msg
     */
    @Override
    public void login(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        if (pile == null) {
            return;
        }
//        logger.info("power ={}", ChargeProcessDataTest.getInstance().getPower());
        //TODO 可能需要事务
        chargeMessageService.login(pile);

        //推送至羊城通
        //commandNotify.sendYccPileStatus(pile.getId());

        //分布式需要放在设备直联机中
        //exOrderTask.removeTask(pile.getPileRtua());
    }

    /**
     * 处理桩的登出指令A2
     * 桩改变离线状态，添加桩的异常结算定时器（如果桩有枪在充电），添加改变用户充电 枪状态定时器，发送数据到羊城充
     *
     * @param msg
     * @return
     */
    @Override
    public void logout(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        if (pile == null) {
            return;
        }

        //TODO 可能需要事务
        chargeMessageService.loginOut(pile);
    }

    /**
     * 处理心跳指令（桩）指令
     *
     * @param msg
     * @return
     */
    @Override
    public void hearBeat(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        //TODO 可能需要事务
        //chargeMessageService.hearBeat(pile, msg);
        //asyncTask.hearBeat(pile, msg);

        chargeMessageService.hearBeat(pile, msg);
        //枪状态发生变化则推送
        //if (result.getNotifyEpNoA() != null) {
        //    commandNotify.notification_stationsStatus(result.getNotifyEpNoA());
        //}
        //if (result.getNotifyEpNoB() != null) {
        //    commandNotify.notification_stationsStatus(result.getNotifyEpNoB());
        //}
    }

    /**
     * 充电数据自动上报 获取充电数据并存入redis中
     */
    @Override
    public void chargeReport(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        //业务处理
        ChargeReportRet ret = chargeMessageService.chargeReport(pile, msg);

        StopChargeReq stopChargeRequest = new StopChargeReq();
        stopChargeRequest.setStopType(ret.getStopType());
        stopChargeRequest.setCmdCode(SocketConstant.POWER_STOP);
        stopChargeRequest.setOrderNum(ret.getOrderNum());
        stopChargeRequest.setElecPileId(pile.getElecPileId());

        //todo 发送停止指令
        if (ret.getStopType() != SocketConstant.STOP_NORMAL_0X0) {

            //远程调用停止指令
            chargerClientRouter.query_stop_charge(stopChargeRequest);
            //commandService.query_stop_charge(stopChargeRequest);

            if (ret.getStopType() == SocketConstant.STOP_BALANCE_LOW_0x6) {
                logger.warn("chargeReport:该订单：" + ret.getOrderNum() + "余额不足0.5元，,发送充电结束指令");
            } else if (ret.getStopType() == SocketConstant.STOP_ELEC_PRICE_EXCEPTION_0x5) {
                logger.warn("chargeReport:该订单：" + ret.getOrderNum() + "电价异常停止,发送充电结束指令");
            } else if (ret.getStopType() == SocketConstant.STOP_IS_ORDER_0XD) {
                logger.warn("chargeReport:该订单：" + ret.getOrderNum() + "平台订单已结算,发送充电结束指令");
            }
        }
        /**添加结算定时器,包含电流过低定时器,充满定时器 **/
        if (ret.getStopType() != SocketConstant.STOP_IS_ORDER_0XD && START_TASK == SocketConstant.CON1) {
            //addTaskByElecAndSoc(ret, pile);

            //站点soc阈值判断是否需要停止
            addTaskByElecStation(ret, pile);

            //站点最高温度阈值判断
            addLimitBatteryTemp(ret, pile);
        }
    }

    /**
     * 读取控制充电的操作结果
     */
    @Override
    public void readElecControl(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        ChargeControlRet ret = chargeMessageService.readElecControl(pile, msg);
    }

    /**
     * 收到A6指令做结算处理
     *
     * @param msg
     * @return
     */
    @Override
    public void chargeBalance(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        chargeMessageService.chargeBalace(pile, msg);
    }

    @Override
    public void startChargeReport(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        ChargeControlRet ret = chargeMessageService.readElecControl(pile, msg);
    }

    @Override
    public void stopChargeReport(TerminalMessage msg) {
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        ChargeControlRet ret = chargeMessageService.readElecControl(pile, msg);
    }

    /**
     * 电桩告警报文解析
     */
    @Override
    public void elecPileFault(TerminalMessage msg) {
        //获取桩
        ElecPile pile = elecPileService.selectPileByLogicAddress(msg.getRtua());

        //解析告警记录
        FaultCodeResult result = new FaultCodeResult();
        List<FaultCodeResult> fcr = result.getResult(msg.getData());

        //将电桩告警记录推送cloud
        for (FaultCodeResult faultCodeResult : fcr) {

            //封装的对象
            ElecPileFaultRecordLog log = new ElecPileFaultRecordLog(faultCodeResult, pile);
            //插入mongdb
            elecPileFaultRecordLogAssemble.assembleTenantOperateLog(log);
        }
    }


    /**
     * 断电指令
     * 会上报两次，以第二次为准
     */
    @Override
    public void powerOff(TerminalMessage msg) {
        ElecPile elecPile = elecPileService.selectPileByLogicAddress(msg.getRtua());
        //断电指令记录
        Result result = new PowerOffResult();

        PowerOffResult powerOffResult = result.getResult(msg.getData());

        if (powerOffResult.getStatus().endsWith(SocketConstant.CON1 + "")) {
            logger.warn("电桩:{}断电成功", elecPile.getPileNo());
        } else {
            logger.error("电桩:{}断电失败", elecPile.getPileNo());
        }
    }

    @Override
    public void timing(TerminalMessage msg) {

    }


    /**
     * 满足条件则添加结算定时器，不满足则删除
     *
     * @param elec     电流
     * @param soc      百分比
     * @param pile     电桩
     * @param gunNum   枪号
     * @param orderNum 订单号
     */
    //void addTaskByElecAndSoc(ChargeReportRet ret, ElecPile pile) {
    //
    //    //花都机械城专用
    //    if (ret.getMemberId() == 63761L || ret.getMemberId() == 215657L) {
    //        /**  电池大于99%，并且电流小于10A  **/
    //        if (ret.getSoc().compareTo(new BigDecimal("99")) >= 0 && ret.getElec().compareTo(new BigDecimal("10")) < 0) {
    //            if (!elecFullTask.hasTask(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum())) {
    //                /**添加充满定时器**/
    //                elecFullTask.addTask(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum(), elecFullTask.TASKSLEPPE_MINUTES, null);
    //                return;
    //            }
    //        } else {
    //            /**删除充满定时器**/
    //            elecFullTask.removeTask(DataUtil.getKey(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum()));
    //            return;
    //        }
    //    }
    //
    //    //其他用户
    //    Integer preSoc = memberService.compareLimitSoc(ret.getMemberId(), pile.getElecStationId());
    //    //if (ret.getPreSoc() != null) {
    //    //    preSoc = ret.getPreSoc();
    //    //}
    //
    //
    //    //如果到达预设soc的值,或者soc=100 则马上停止
    //    if (preSoc.intValue() <= ret.getSoc().intValue() || ret.getSoc().intValue() == 100) {
    //        elecFullTask.addTask(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum(), 1, TimeUnit.SECONDS);
    //        return;
    //    }
    //
    //
    //    /**  电池大于设定值 <=98充电10分钟停止, 大于98则充电5分钟后停止 **/
    //    if (ret.getSoc().intValue() >= 98 && !elecFullTask.hasTask(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum())) {
    //        /**添加充满定时器**/
    //        elecFullTask.addTask(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum(), 5, null);
    //        return;
    //    }
    //
    //
    //    //如果不满足条件则删除定时器
    //    if (ret.getSoc().intValue() < 98 && ret.getSoc().intValue() < preSoc.intValue() && elecFullTask.hasTask(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum())) {
    //        /**删除充满定时器**/
    //        elecFullTask.removeTask(DataUtil.getKey(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum()));
    //    }
    //
    //
    //}


    /**
     * 满足条件则添加结算定时器，不满足则删除
     */
    void addTaskByElecStation(ChargeReportRet ret, ElecPile pile) {

        //其他用户
        Integer limitSoc = elecStationService.selectLimitSoc(pile.getElecStationId(), SocketConstant.CON0);

        if (limitSoc == null || ret.getSoc() == null) {
            return;
        }

        //如果到达预设soc的值,或者soc=100 则马上停止
        if (limitSoc.intValue() <= ret.getSoc().intValue()) {
            logger.info("达到站点设置域名停止,订单soc:{},订单号:{}", ret.getSoc(), ret.getOrderNum());
            elecFullTask.addTask(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum(), 1, TimeUnit.SECONDS);
            return;
        }
    }


    /**
     * 设置阈值
     *
     * @param ret
     * @param pile
     */
    void addLimitBatteryTemp(ChargeReportRet ret, ElecPile pile) {

        //其他用户
        Integer batteryTemp = elecStationService.selectLimitSoc(pile.getElecStationId(), SocketConstant.CON1);

        if (batteryTemp == null || batteryTemp == 0) {
            return;
        }

        //如果到达预设soc的值,或者soc=100 则马上停止
        if (batteryTemp.intValue() <= ret.getBatteryTemp().intValue()) {
            logger.info("达到站点设置最高温度停止,订单soc:{},订单号:{}", ret.getSoc(), ret.getOrderNum());
            //batteryTempTask.addTask(pile.getPileRtua(), ret.getGunNum(), ret.getOrderNum(), 1, TimeUnit.SECONDS);

            OrderInfo orderInfo = orderInfoService.selectByOrderNum(ret.getOrderNum());
            if (orderInfo == null) {
                return;
            }
            StopChargeReq stopChargeRequest = new StopChargeReq();
            stopChargeRequest.setOrderId(orderInfo.getOrderId());
            stopChargeRequest.setOrderNum(orderInfo.getOrderNum());
            stopChargeRequest.setStopType(SocketConstant.STOP_BATTERY_TEMP_0X10);
            stopChargeRequest.setElecPileId(orderInfo.getElecPileId());

            //远程调用停止指令
            chargerClientRouter.query_stop_charge(stopChargeRequest);

            return;
        }
    }

    protected boolean htChargeTime() {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
            //Date beginDate1 = sdf.parse("14:00");
            //Date endDate1 = sdf.parse("17:00");
            //
            //Date beginDate2 = sdf.parse("19:00");
            //Date endDate2 = sdf.parse("22:00");
            Date beginDate1 = sdf.parse("08:00");
            Date endDate1 = sdf.parse("12:00");

            Date beginDate2 = sdf.parse("14:00");
            Date endDate2 = sdf.parse("19:00");

            Date nowDate = sdf.parse(sdf.format(new Date()));
//            Date nowDate = sdf.parse("21:00");
            if (nowDate.getTime() >= beginDate1.getTime() && nowDate.getTime() <= endDate1.getTime()) {
                return true;
            }
            if (nowDate.getTime() >= beginDate2.getTime() && nowDate.getTime() <= endDate2.getTime()) {
                return true;
            }
            return false;
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }
    }
}
